<?php

/*
 * Admin:
 * Class to control the Admin section.
 * 
 * TODO: Make nav automatically generated from the functions in the class.
 */
class Admin extends Controller
{
	public function __construct()
	{
		parent::Controller();
		$this->load->model('Phlare');
		$this->load->model('Page_tree');
	}
	
	/**
	 * index:
	 * default function run if none specified. This is the content page.
	 * 
	 * @return view
	 */
	public function index()
	{
		// Set up arrays for view data
		$header_data = array(
			'current_page' => 'content'
		);
		
		$data = array(
			'page_types' => $this->get_models_of_type('Page'), // The page types
			'tree' => $this->Page_tree->get_page_tree_stage() // The page tree
		);
		
		$this->load->view('admin/includes/head');
		$this->load->view('admin/includes/header', $header_data);
		$this->load->view('admin/index', $data);
		$this->load->view('admin/includes/footer');
	} // end index
	
	
	public function ajax_get_page_tree()
	{
		if(isset($_POST['root']))
		{
			$result = array();
			
			if($_POST['root'] === 'source')
			{
				$result[] = array(
					'text' => 'Site Content',
					'expanded' => false,
					'hasChildren' => true,
					'classes' => 'folder',
					'id' => $this->Page_tree->get_site_root()
				);
			}
			else
			{
				$pages = $this->Page_tree->get_page_tree_stage($_POST['root']);
				
				foreach($pages as $page)
				{
					$data = array(
						'menu_title' => $page->menu_title,
						'page' => $page
					);
					
					$result[] = array(
						'text' =>$this->load->view('admin/ajax_get_page_tree', $data, true),
						'expanded' => false,
						'hasChildren' => ($page->right_val == $page->left_val+1) ? false : true,
						'classes' => ($page->right_val == $page->left_val+1) ? 'file' : 'folder',
						'id' => $page->id
					);
				}
			}
			
			$this->ajax_result($result);
		}
	} // end ajax_get_page_tree
	
	
	public function create()
	{
		if(isset($_POST['create_new_page']) && isset($_POST['page_type']) && strlen($_POST['page_type']))
		{
			$this->load->helper('url');
			
			// Set up arrays for view data
			$header_data = array(
				'current_page' => 'content'
			);
			
			// Load the requested model as 'new_page_model' so it's easy to refer to:
			$this->load->model($_POST['page_type'], 'new_page_model');
			
			// Need to get field types for this page type
			$data = array(
				'page_types' => $this->get_models_of_type('Page'),
			    'tree' => $this->Page_tree->get_page_tree_stage(), // The page tree
			    'page_type' => $_POST['page_type'],
				'new_page_model_name' => ucfirst(str_replace('_', ' ', $_POST['page_type'])),
				'site_address' => base_url(),
				'new_page_fields' => $this->new_page_model->get_db_fields(),
				'new_page_tabs' => $this->new_page_model->get_tabs()
			);
			
			$this->load->view('admin/includes/head');
			$this->load->view('admin/includes/header', $header_data);
			$this->load->view('admin/create', $data);
			$this->load->view('admin/includes/footer');
		}
		else
		{
			session_write_close();
			header('Location: /admin/index/');
			exit();
		}
	} // end create
	
	public function ajax_do_create()
	{
		if(isset($_POST['object_class']))
		{
		    $object_class = $_POST['object_class'];
		    $edit_object = new $object_class();
		    $object_info_array = $edit_object->create($_POST);
		    
		    // Tell page tree about the new page
			$this->Page_tree->new_page_tree_row(
				$object_info_array['object_id'],
				$object_info_array['version_id'],
				$object_class,
				1, // Parent ID
				NULL, // Left value
				NULL, // Right value
				'stage'
			);
			
			$site_root = $this->Page_tree->get_site_root();
			
			if($site_root)
			{
			    $this->Page_tree->rebuild_tree(
    				$site_root, // Site Root ID
    				1 // Initital left ID
    			);
			}
		    
		    $this->ajax_result(
				array(
					'message_class' => 'valid',
					'message' => 'Page created!'
				)
			);
			
		}
	} // end do_create
	
	
	public function ajax_get_edit()
	{
		if(isset($_POST['object_class']) && isset($_POST['object_id']) && isset($_POST['object_version']))
		{
			// Variables come from POST
			$object_class = $_POST['object_class'];
			$object_id = $_POST['object_id'];
			$object_version = $_POST['object_version'];
			
			$this->load->helper('url');
			
			$edit_object = new $object_class($object_id, $object_version);
			
			$data = array(
				'site_address' => base_url(),
				'object_class' => $object_class,
				'object_id' => $object_id,
				'object_version' => $object_version,
				'page_title' => $edit_object->page_title,
				'fields' => $edit_object->get_db_fields(),
				'tabs' => $edit_object->get_tabs()
			);
			
			$this->load->view('admin/edit', $data);
		}
	} // end ajax_get_edit
	
	/**
	 * ajax_do_edit:
	 * Acceptable css classes to return are "error", "warning", and "valid".
	 * 
	 * @return json object
	 */
	public function ajax_do_edit()
	{
		if(isset($_POST['object_class']) && isset($_POST['object_id']) && isset($_POST['object_version']))
		{
			// Get the current version of the object
			$edit_object = new $_POST['object_class']($_POST['object_id'], $_POST['object_version']);
			
			// Get the page tree data
			$page_tree_data = $this->Page_tree->get_page_tree_row($_POST['object_class'], $_POST['object_id'], $_POST['object_version']);
			
			// Previous stage pages becomes history pages
			$this->Page_tree->stage_to_history($_POST['object_class'], $_POST['object_id']);
			
			// Update the page
			$next_object_version = $edit_object->update($_POST);
			
			// Tell page tree about the new page
			$this->Page_tree->new_page_tree_row(
				$page_tree_data->object_id,
				$next_object_version,
				$page_tree_data->object_class,
				$page_tree_data->parent_id,
				$page_tree_data->left_val,
				$page_tree_data->right_val,
				'stage'
			);
			
			
			// If we are publishing... do the live bit
		}
		else
		{
			// Return error
			$this->ajax_result(
				array(
					'message_class' => 'error',
					'message' => 'Error! Insufficient data submitted to edit the page.'
				)
			);
		}
	} // end ajax_do_edit
	
	protected function ajax_result($data)
	{
		header('Content-type: application/x-json');
		echo json_encode($data);
	} // end ajax_result
	
	public function database()
	{
		// Get list of models to display:
		$models = $this->Phlare->get_model_list();
		
		// Set up arrays for view data
		$header_data = array(
			'current_page' => 'database'
		);
		$data = array();
		
		foreach($models as $class => $model)
		{
			// Load the model if it's not already loaded
			if(!isset($this->$model))
			{
				$this->load->model($model);
			}
			
			// Pull out the DB fields (we only want to show classes with fields containing something)
			if(
				count($this->$model->get_db_fields())
			)
			{
				$table_exists = $this->$model->check_table_exists();
				if($table_exists)
				{
					$table_up_to_date = $this->$model->check_table_up_to_date();
				}
				else
				{
					$table_up_to_date = false;
				}
				
				
				$data['fields'][$class] = $this->$model->get_db_fields();
				$data['tables'][$class]['table_exists'] = $table_exists;
				$data['tables'][$class]['table_up_to_date'] = $table_up_to_date;
				
				// See if we need to create the table
				if(isset($_POST['action']) && $_POST['action'] === 'update_db' && !$table_exists)
				{
					// Make the table
					$this->$model->create_table();
					$data['tables'][$class]['table_exists'] = true;
					$data['tables'][$class]['table_up_to_date'] = true;
				}
				elseif(isset($_POST['action']) && $_POST['action'] === 'update_db' && !$table_up_to_date)
				{
					$this->$model->update_table();
					$data['tables'][$class]['table_up_to_date'] = true;
				}
				
			}
		}
		
		$this->load->view('admin/includes/head');
		$this->load->view('admin/includes/header', $header_data);
		$this->load->view('admin/database', $data);
		$this->load->view('admin/includes/footer');
	} // end database
	
	
	public function ajax_rebuild_menu()
	{
		$site_root = $this->Page_tree->get_site_root();
		
		if($site_root !== false)
		{
			$this->Page_tree->rebuild_tree(
				$site_root, // Site Root ID
				1 // Initital left ID
			);
			$class = 'valid';
			$message = 'Menu has been rebuilt.';
		}
		else
		{
			$class = 'error';
			$message = 'Error! Could not determine site root. This indicates a critical problem with the database.
				Contact the administrator immediately.';
		}
		
		$this->ajax_result(
			array(
				'message_class' => $class,
				'message' => $message
			)
		);
		
	} // end rebuild_menu
	
	
	public function about()
	{
		// Set up arrays for view data
		$header_data = array(
			'current_page' => 'about'
		);
		
		$this->load->view('admin/includes/head');
		$this->load->view('admin/includes/header', $header_data);
		$this->load->view('admin/about');
		$this->load->view('admin/includes/footer');
	} // end about
	
	
	//-------------------------------------------------------------[ Private Helper Functions
	
	/**
	 * get_models_of_type:
	 * Return a list of all models that are of a certain type, or extended it.
	 * 
	 * @return array
	 * @param object $model_type
	 */
	private function get_models_of_type($model_type)
	{
		$return_models = array();
		
		$all_models = $this->Phlare->get_model_list();
		
		foreach($all_models as $class => $model)
		{
			// Load the model if it's not already loaded
			if(!isset($this->$model))
			{
				$this->load->model($model);
			}
			
			if(
				is_a($this->$model, $model_type)
				||
				is_subclass_of($this->$model, $model_type)
			)
			{
				$return_models[$class] = $model;
			}
		}
		
		return $return_models;
	} // end get_models_of_type
	
} // end Admin
